package com.meltingslime.asciifight.server.network;

import com.meltingslime.asciifight.server.ASCIIFightServer;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Timer;

/**
 * @author Exit93
 * @version 1.0
 */
public class ConnectionListener extends Thread {

    private InetAddress ip;
    private int port;

    private ServerSocket server = null;
    private boolean listening = false;

    private ArrayList<Client> clients = new ArrayList<Client>();
    private Timer cleaner = new Timer(true);

    private Logger log = Logger.getLogger("asciifight.server");

    public ConnectionListener (InetAddress ip, int port){
        super.setName("ListenerThread");
        this.ip = ip;
        this.port = port;
        cleaner.scheduleAtFixedRate(new ClientsCleanerTask(clients),
                ASCIIFightServer.Config.getClientCleanerInterval() * 60 * 1000,
                ASCIIFightServer.Config.getClientCleanerInterval() * 60 * 1000);
    }

    private void bindListener(){
        if (server != null && !server.isClosed() && server.isBound()){
            return;
        }
        try {
            server = new ServerSocket(port, 0, ip);
        } catch (IOException e) {
            log.fatal("Cannot create SocketServer", e);
            System.exit(3);
        }
    }

    public void startListening(){
        bindListener();
        log.info("Now listening for connections");
        listening = true;
        start();
    }

    public void stopListening(){
        if (!isListening())
            return;
        listening = false;
        log.info("Stopping Listener");
        try {
            server.close();
        } catch (IOException ignore) {}
    }

    public boolean isListening(){
        return listening;
    }

    public void run(){
        while (listening){
            try {
                Client cl = new Client(server.accept());
                synchronized (ClientsCleanerTask.class){
                    clients.add(cl);
                }
            } catch (IOException e) {
                if (!isListening()) // Closing the listener
                    return;
                log.error("An error occurred while accepting a client.", e);
                bindListener(); // Restart listening in case it stopped working
            }
        }
    }
}
